
use super::math;


type List<T> = ::std::vec::Vec<T>;



#[derive(Debug)]
#[derive(Clone)]
#[derive(Default)]
pub enum ShapeType
{
    #[default]
    None,
    Rectangle(f64, f64),/// width: f64, height: f64
    Polygon(List<math::Point>),
    Circle(f64) // radius
}
impl core::cmp::PartialEq for ShapeType
{
    fn eq(&self, other: &Self) -> bool
    {
        let mut none: u8 = 0;
        let mut rectangle: u8 = 0;
        let mut polygon: u8 = 0;
        let mut circle: u8 = 0;
        match self {
            ShapeType::None => none += 1,
            ShapeType::Rectangle(_, _) => rectangle += 1,
            ShapeType::Polygon(_) => polygon += 1,
            ShapeType::Circle(_) => circle += 1,
        };
        match other {
            ShapeType::None => none += 1,
            ShapeType::Rectangle(_, _) => rectangle += 1,
            ShapeType::Polygon(_) => polygon += 1,
            ShapeType::Circle(_) => circle += 1
        };
        if none == 2 || rectangle == 2 || polygon == 2 || circle == 2 { return true; }
        false
    }
}


#[derive(Debug)]
#[derive(Clone)]
#[derive(Default)]
pub enum ShapePosition
{
    #[default]
    None,
    Rectangle(math::Rectangle),
    Polygon(List<math::Point>),
    Circle(math::Circle) // radius
}
impl ShapePosition
{

}


/// 存储shape的图形信息，可用position()获取在某一位置的信息
#[derive(Debug)]
#[derive(Clone)]
#[derive(Default)]
pub struct Shape
{
    pub r#type: ShapeType,
    pub angle: f64,     // 角度，暂时未使用到
}
impl Shape
{
    pub fn new(r#type: ShapeType) -> Self
    {
        Self {
            r#type,
            angle: 0.0
        }
    }

    pub fn r#type(&self) -> &ShapeType { &self.r#type }
    pub fn get_type(&self) -> &ShapeType { &self.r#type }


    /**
     * 待修改
     */
    pub fn position(&self, position: math::Vector2) -> ShapePosition
    {
        let x = position.x;
        let y = position.y;

        match &self.r#type {
            ShapeType::Rectangle(w, h) => {
                ShapePosition::Rectangle(
                    math::Rectangle {
                        left: x,
                        top: y,
                        right: x + w,
                        bottom: y + h,
                    }
                )
                
            },
            ShapeType::Polygon(points) => {
                let mut list = points.clone();
                for p in &mut list
                {
                    p.x += x;
                    p.y +=y;
                }
                ShapePosition::Polygon(list)
            },
            ShapeType::Circle(r) => {
                ShapePosition::Circle(
                    math::Circle {
                        center: math::Point { x, y },
                        radius: r.clone(),
                    }
                )
            },
            ShapeType::None => todo!(),
        }
    }
    pub fn get_position(&self, position: math::Vector2) -> ShapePosition { self.position(position) }

}




#[derive(Debug)]
#[derive(Clone)]
#[derive(Default)]
pub struct Body
{
    pub name: String,
    pub mass: f64,                          // 质量，单位kg
    pub density: f64,                       // 密度 浮力相关 人类约1.02
    center: math::Vector2,                  // 中心位置
    angle: f64,                             // 角度
    accelerate: math::Vector2,              // 加速度
    linear_velocity: math::Vector2,         // 直线速度
    angular_velocity: f64,                  // 角速度
    pub elasticity: f64,                    // 弹性；弹力
    pub roughness: f64,                     // 粗糙度
    pub force: math::Vector2,               // 受力
    pub friction: f64,                      // 摩擦力
    pub gravity: f64,                       // 重力
    pub supported: bool,                    // 是否受到支持

    pub shape: Shape,                       // 形状
    pub position: math::Vector2,
}
pub type BodyList = List<Body>;
impl Body
{
    pub fn new() -> Self { Default::default() }
    pub fn shape_position(&self) -> ShapePosition { self.shape.position(self.position) }
    pub fn get_shape_position(&self) -> ShapePosition { self.shape.position(self.position) }

    pub fn cross_rectangle(&mut self, other: &Self) -> bool
    {
        let p1;
        let p2;
        match &self.shape.r#type {
            ShapeType::Rectangle(_, _) => {
                p1 = self.shape.position(self.position);
            },
            _ => return false
        }
        match &other.shape.r#type {
            ShapeType::Rectangle(_, _) => {
                p2 = other.shape.position(other.position)
            },
            _ => return false
        }

        if let ShapePosition::Rectangle(r1) = p1
        {
            if let ShapePosition::Rectangle(r2) = p2
            {
                if r1.cross(&r2) {
                    if self.mass == 0.0 { return true; }

                    // 判断是否是与底下的东西相交
                    let r2height = r2.bottom - r2.top;
                    let r2height_0_1 = r2height / 10.0;

                    if  r1.bottom >= r2.top
                        && r1.bottom <= r2.top + r2height_0_1
                        && r1.top < r2.top
                    {
                        self.supported = true;
                        self.position.y = r2.top - (r1.bottom - r1.top);
                    } else { if self.supported {self.supported = false;} }
                    
                    return true;
                }
            } else { panic!() }
        } else { panic!() }
        false
       
    }


    pub fn cross_polygon(&mut self, other: &Self) -> bool
    {
        let p_self;
        let p_other;
        match &self.shape.r#type {
            ShapeType::Polygon(_) => p_self = self.shape.position(self.position),
            _ => return false
        }
        match &other.shape.r#type {
            ShapeType::Polygon(_) => p_other = other.shape.position(other.position),
            _ => return false
        }

        let points_self = if let ShapePosition::Polygon(p) = &p_self {
            p
        } else { panic!(); };
        let points_other = if let ShapePosition::Polygon(p) = &p_other {
            p
        } else { panic!(); };

        let mut segment_self: List<math::Segment> = List::new();
        let mut segment_other: List<math::Segment> = List::new();
        let 遍历points并创建线段 = |points: &List<math::Point>, segment_list: &mut List<math::Segment>| {
            for i in 0..points.len() {
                let mut i2 = i + 1;
                if i2 == points.len() {
                    i2 = 0;
                }
                segment_list.push(math::Segment::new(points_self[i],points_self[i2]))
            }
        };
        遍历points并创建线段(points_self, &mut segment_self);
        遍历points并创建线段(points_other, &mut segment_other);
        
        let 判断某线段是否与一堆线段相交and若遇到有就返回真 = |s: &math::Segment, s_list: &List<math::Segment>| -> bool {
            for 某线段 in s_list {
                if s.cross(某线段) { return true; }
            }
            false
        };
        for s in &segment_self {
            if 判断某线段是否与一堆线段相交and若遇到有就返回真(s, &segment_other) {
                return true;
            }
        }

        false
    }



    pub fn cross(&mut self, other: &Self) -> bool
    {
        /* 形状一样 */
        if self.shape.r#type == other.shape.r#type
        {
            match &self.shape.r#type
            {
                ShapeType::Rectangle(_, _) => {
                    return self.cross_rectangle(&other);
                }
                ShapeType::Polygon(_) => {
                    /* Polygon 与 Polygon */
                    return self.cross_polygon(other);
                },
                ShapeType::Circle(_) => {
                    /* Circle 与 Circle */
                },
                ShapeType::None => {}
            }
        }

        /* 形状不一样 */
        /* Polygon 与 Circle */

        false
    }


    /**
     * 修改重力
     * g 是 重力加速度
     * */
    pub fn set_gravity(&mut self, g: f64)
    {
        self.gravity = self.mass * g;
    }


    /// 请修改数据后再执行这个
    /// 这个不好使，不建议用
    pub fn update(&mut self, timedelta_seconds: f64)
    {
        // 同步 angle
        if self.shape.angle != self.angle
        {
            self.shape.angle = self.angle;
        }

        // 质量为 0 的东西不大科学
        if self.mass == 0.0 { return; }

        // 受到支持
        if self.supported {
            self.accelerate.y = 0.0;
            self.linear_velocity.y = 0.0;
        }

        // 更新加速度
        // F = ma
        // |a| = (x * x + y * y).sqrt()
        let force_sum = math::Vector2 { x: self.force.x, y: self.force.y + self.gravity };
        self.accelerate.x = force_sum.x / self.mass;
        self.accelerate.y = force_sum.y / self.mass;

        // 更新速度
        self.linear_velocity.x += self.accelerate.x * timedelta_seconds;// 每秒速度
        self.linear_velocity.y += self.accelerate.y * timedelta_seconds;// 每秒速度

        // 更新位置
        let 位移x = self.linear_velocity.x * timedelta_seconds;
        let 位移y = self.linear_velocity.y * timedelta_seconds;
        self.position.x += 位移x;
        self.position.y += 位移y;
    }


    pub fn collide_swap_force(&mut self, other: &mut Self)
    {
        /* 虚假的物理 */
        // 摩檫力
        let miu = self.roughness * other.roughness;
        self.friction = miu * self.gravity;
        other.friction = miu * other.gravity;

        let force模长_self = self.force.length();
        let 单位向量;
        if force模长_self == 0.0 {
            单位向量 = math::Vector2 { x: 0.0, y: 0.0 };
        }
        else {
            单位向量 = math::Vector2 { x: self.force.x / force模长_self, y: self.force.y / force模长_self };
        }
        let 摩檫力向量_self = -math::Vector2 { x: 单位向量.x * self.friction, y: 单位向量.y * self.friction };//注意，方向与force的相反


        let force模长_other = other.force.length();
        let 单位向量;
        if force模长_other == 0.0 {
            单位向量 = math::Vector2 { x: 0.0, y: 0.0 };
        }
        else {
            单位向量 = math::Vector2 { x: other.force.x / force模长_other, y: other.force.y / force模长_other };
        }
        let 摩檫力向量_other = -math::Vector2 { x: 单位向量.x * other.friction, y: 单位向量.y * other.friction };//注意，方向与force的相反


        // 力的方向
        let mut 力的方向_self: i8 = 0;// 0 不用管，-1 为 左边， 1 为 右边
        let mut 力的方向_other: i8 = 0;// 0 不用管，-1 为 左边， 1 为 右边
        let k_self = self.force.tan();
        let k_other = other.force.tan();
        if k_self == 0.0 {
            if self.force.x > 0.0 {
                力的方向_self = 1;
            } else if self.force.x < 0.0 { 
                力的方向_self = -1;
            }
        }
        if k_other == 0.0 {
            if self.force.x > 0.0 {
                力的方向_other = 1;
            } else if self.force.x < 0.0 { 
                力的方向_other = -1;
            }
        }

        // 第一象限角
        if self.force.x > 0.0 && self.force.y > 0.0 {
            力的方向_self = 1;
        }
        // 第四象限角
        else if self.force.x > 0.0 && self.force.y < 0.0 {
            力的方向_self = 1;
        }
        // 第二象限角
        else if self.force.x < 0.0 && self.force.y > 0.0 {
            力的方向_self = -1;
        }
        // 第三象限角
        else if self.force.x < 0.0 && self.force.y < 0.0 {
            力的方向_self = -1;
        }
        

        // 第一象限角
        if other.force.x > 0.0 && other.force.y > 0.0 {
            力的方向_other = 1;
        }
        // 第四象限角
        else if other.force.x > 0.0 && other.force.y < 0.0 {
            力的方向_other = 1;
        }
        // 第二象限角
        else if other.force.x < 0.0 && other.force.y > 0.0 {
            力的方向_other = -1;
        }
        // 第三象限角
        else if other.force.x < 0.0 && other.force.y < 0.0 {
            力的方向_other = -1;
        }


        let force_sum_self = math::Vector2 { x: self.force.x, y: self.force.y + self.gravity };
        let force_sum_other = math::Vector2 { x: other.force.x, y: other.force.y + other.gravity };
        let 力的大小_self = force_sum_self.length();
        let 力的大小_other = force_sum_other.length();


        // 力都向左边
        if 力的方向_self == 力的方向_other && 力的方向_self == -1
        {
            if 力的大小_self > 力的大小_other
            {
                
            }
            else if 力的大小_self < 力的大小_other
            {
                
            }
            
        }
        // 力都向右边
        else if 力的方向_self == 力的方向_other && 力的方向_self == 1
        {
            if 力的大小_self > 力的大小_other
            {
                
            }
            else if 力的大小_self < 力的大小_other
            {
                
            }
        }
        // 力的方向：self左，other右
        else if 力的方向_self != 力的方向_other && 力的方向_self == -1
        {
            if 力的大小_self > 力的大小_other
            {
                
            }
            else if 力的大小_self < 力的大小_other
            {
                
            }
        }
        // 力的方向：self右，other左
        else if 力的方向_self != 力的方向_other && 力的方向_self == 1
        {
            if 力的大小_self > 力的大小_other
            {
                
            }
            else if 力的大小_self < 力的大小_other
            {
                
            }
        }


        // 力的变更
        let value = self.force + other.force;// 合力
        let reaction_to_self = -force_sum_self + 摩檫力向量_self;// 反作用力
        let reaction_to_other = -force_sum_other + 摩檫力向量_other;// 反作用力

        if 力的大小_self > 力的大小_other
        {
            other.force = value + reaction_to_other;
            self.force += reaction_to_self;
        }
        // 力给速度小的
        else if 力的大小_self == 力的大小_other {
            if self.linear_velocity > other.linear_velocity
            {
                other.force = value + reaction_to_other;
                self.force += reaction_to_self;
            } else {
                self.force = value + reaction_to_self;
                other.force += reaction_to_other;
            }
        }
        else {
            self.force = value + reaction_to_self;
            other.force += reaction_to_other;
        }

        self.accelerate.x = 0.0;
        self.accelerate.y = 0.0;
        self.linear_velocity.x = 0.0;
        other.accelerate.x = 0.0;
        other.accelerate.y = 0.0;
        other.linear_velocity.x = 0.0;
    }

}


